package com.dengyafei.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * @author 邓亚非
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    /**
     * 环绕通知
     *
     * @param proceedingJoinPoint
     * @return
     */
    @Around("execution(public * com.dengyafei.service.impl..*.*(..))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        //        接收请求,记录请求内容
        ServletRequestAttributes attributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        //        打印日志信息
        long startTime = System.currentTimeMillis();
        log.info("请求url:{}", request.getRequestURL().toString());
        log.info("请求方式:{}", request.getMethod());
        log.info("请求ip:{}", request.getRemoteAddr());
        log.info(
                "请求方法所在类:[{}]",
                proceedingJoinPoint.getSignature().getDeclaringTypeName(),
                ".",
                proceedingJoinPoint.getSignature().getName());
        log.info("请求参数:{}", Arrays.toString(proceedingJoinPoint.getArgs()));
        //        返回值
        Object result = proceedingJoinPoint.proceed(proceedingJoinPoint.getArgs());
        log.info("请求结束时间:{}", LocalDateTime.now());
        log.info("请求耗时:{}", (System.currentTimeMillis() - startTime));
        log.info("请求返回:{}", request);
        return result;
    }

    /**
     * 异常通知
     *
     * @param throwable
     */
    @AfterThrowing(
            value = "execution(public * com.dengyafei.service.impl..*.*(..))",
            throwing = "throwable")
    public void throwing(Throwable throwable) {
        log.error("发生异常时间:{}", LocalDateTime.now());
        log.error("抛出异常:{}", throwable.getMessage());
    }
}
